今天來介紹一下內存洩漏相關的知識,野指針
以及如何去發現這類問題的工具valgrind
野指針
在Day14 Crashlog中有提到其中一種,對空指針變量進行存取
,參考下面例子
int *a = nullptr;
a[1] = 10; // 會導致程式崩潰
若對指針變數使用兩次以上free
或delete
也會造成野指針
char* str = (char *)malloc (1024);
free(str);
free(str); // 野指針一種
指針操作超出變量作用範圍也會,參考下面例子
Cat *pCat; // Cat 為class
{
Cat cat2;
pCat = &cat2; // cat2的生命週期,只存在大括號裡面
}
pCat->Meow(); // pCat變野指針
Valgrind
是一款可以用來檢測程式是否有非法使用內存的工具,就是剛剛上面提到的野指針
這類的問題,實際上我們用的是valgrind
中的其中一個工具memcheck
,他裡面還有很多工具,針對緩存、多線程等檢測工具,這邊就暫時不介紹了
如果是用之前dockerfile
啟的環境,valgrind
應該是已經安裝好的,因為CentOS devtoolset
中就有包含valgrind
,這邊真的要安裝也可以參考下面的指令
wget http://sourceware.org/pub/valgrind/valgrind-3.15.0.tar.bz2
tar -jxvf valgrind-3.15.0.tar.bz2
cd valgrind-3.15.0
./configure
make
make install
這邊就先用上次空指針
的例子,來用valgrind
檢查看看
int main()
{
int *a = nulltpr;
a[1] = 10;
return 0;
}
valgrind --tool=memcheck --leak-check=full ./wild_pointer
# valgrind 檢測結果,可以看到valgrind幫我們判斷出哪一行非法使用內存
==28157== Memcheck, a memory error detector
==28157== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==28157== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==28157== Command: ./wild_pointer
==28157==
==28157== Invalid write of size 4
==28157== at 0x400AFC: main (WildPointer.cpp:35)
==28157== Address 0x4 is not stack'd, malloc'd or (recently) free'd
==28157==
==28157==
==28157== Process terminating with default action of signal 11 (SIGSEGV)
==28157== Access not within mapped region at address 0x4
==28157== at 0x400AFC: main (WildPointer.cpp:35)
==28157== If you believe this happened as a result of a stack
==28157== overflow in your program's main thread (unlikely but
==28157== possible), you can try to increase the size of the
==28157== main thread stack using the --main-stacksize= flag.
==28157== The main thread stack size used in this run was 8388608.
==28157==
==28157== HEAP SUMMARY:
==28157== in use at exit: 0 bytes in 0 blocks
==28157== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==28157==
==28157== All heap blocks were freed -- no leaks are possible
==28157==
==28157== For counts of detected and suppressed errors, rerun with: -v
==28157== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
重複釋放記憶體
int main()
{
char* str = (char *)malloc (1024);
free(str);
free(str);
return 0;
}
valgrind --tool=memcheck --leak-check=full ./wild_pointer
# valgrind 檢測結果,檢測出哪邊非法,下面的HEAP SUMMARY可以看到申請一次,可以卻釋放兩次
==29416== Memcheck, a memory error detector
==29416== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==29416== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==29416== Command: ./wild_pointer
==29416==
==29416== Invalid free() / delete / delete[] / realloc()
==29416== at 0x4C2ACBD: free (vg_replace_malloc.c:530)
==29416== by 0x400B19: main (WildPointer.cpp:38)
==29416== Address 0x5a24040 is 0 bytes inside a block of size 1,024 free'd
==29416== at 0x4C2ACBD: free (vg_replace_malloc.c:530)
==29416== by 0x400B0D: main (WildPointer.cpp:37)
==29416== Block was alloc'd at
==29416== at 0x4C29BC3: malloc (vg_replace_malloc.c:299)
==29416== by 0x400AFD: main (WildPointer.cpp:36)
==29416==
cat delete
Meow!
==29416==
==29416== HEAP SUMMARY:
==29416== in use at exit: 0 bytes in 0 blocks
==29416== total heap usage: 1 allocs, 2 frees, 1,024 bytes allocated
==29416==
==29416== All heap blocks were freed -- no leaks are possible
==29416==
==29416== For counts of detected and suppressed errors, rerun with: -v
==29416== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
未釋放記憶體
int main(int argc, char const *argv[])
{
char* str = (char *)malloc (1024);
return 0;
}
valgrind --tool=memcheck --leak-check=full ./wild_pointer
# valgrind 檢測結果,檢測出未釋放的部分
==9567== Memcheck, a memory error detector
==9567== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==9567== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==9567== Command: ./wild_pointer
==9567==
==9567==
==9567== HEAP SUMMARY:
==9567== in use at exit: 1,024 bytes in 1 blocks
==9567== total heap usage: 1 allocs, 0 frees, 1,024 bytes allocated
==9567==
==9567== 1,024 bytes in 1 blocks are definitely lost in loss record 1 of 1
==9567== at 0x4C29BC3: malloc (vg_replace_malloc.c:299)
==9567== by 0x400AA5: main (WildPointer.cpp:34)
==9567==
==9567== LEAK SUMMARY:
==9567== definitely lost: 1,024 bytes in 1 blocks
==9567== indirectly lost: 0 bytes in 0 blocks
==9567== possibly lost: 0 bytes in 0 blocks
==9567== still reachable: 0 bytes in 0 blocks
==9567== suppressed: 0 bytes in 0 blocks
==9567==
==9567== For counts of detected and suppressed errors, rerun with: -v
==9567== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)